package sdiff;

import gnu.getopt.Getopt;

import java.io.IOException;

import net.sourceforge.pmd.cpd.TokenEntry;

import smallChanges.lineNumberMapping.StatementMapper;
import smallChanges.statements.StatementMappingEntry;
import smallChanges.statements.StatementMappingResultSet;
import smallChanges.statements.StatementMappingEntry.StatementMappingStatus;

public class SDiff
{

    /**
     * @param args
     */
    public static void main(String[] args)
    throws IOException
    {
        if (args.length < 2) {
            System.err.println("Usage: java sdiff.SDiff " +
                    "\n[ -j <java-version>, (1.3, 1.4, 1.5), default 1.4 ]\n" +
                    "\n[ -l <line matching threshold, (0 <= X <= 1.0), default 0.4> ]\n" +
                    "\n[ -c <class matching threshold, (0 <= X <= 1.0), default 0.9> ]\n" +
                    "\n[ -f <field matching threshold, (0 <= X <= 1.0), default 2.5> ]\n" +
                    "\n[ -m <method matching threshold, (0 <= X <= 1.0), default 0.9> ]\n" +
            		"<v0> <v1> ");
            System.exit(1);
        }
        
        // defaults
        boolean useTokenEditDistance=false;
        boolean useMinOfTokenOrTextEditDistance=false;
        boolean usePossibleProbable=false;
        
        double canforaThreshold=0.4;
        double classMappingThreshold=0.9;
        double fieldMappingThreshold=2.5;
        double methodMappingThreshold=2.0;
        
        String version="1.4";
        
        Getopt g = new Getopt("sdiff", args, "c:f:j:l:m:tnp");
        //
        int c;
        while ((c = g.getopt()) != -1)
        {
            switch(c)
            {
            case 'c':
                classMappingThreshold=Double.parseDouble(g.getOptarg());
                break;
            case 'f':
                fieldMappingThreshold=Double.parseDouble(g.getOptarg());
                break;
            case 'j':
                version=g.getOptarg();
                break;
            case 'l':
                canforaThreshold=Double.parseDouble(g.getOptarg());
                break;
            case 'm':
                methodMappingThreshold=Double.parseDouble(g.getOptarg());
                break;
            case 't':
                useTokenEditDistance=true;
                break;
            case 'n':
                useMinOfTokenOrTextEditDistance=true;
                break;
            case 'p':
                usePossibleProbable=true;
                break;
            default:
                throw new IllegalArgumentException("getopt() returned " + c + "\n");
            }
        }
        
        String leftFileStr=args[g.getOptind()];
        String rightFileStr=args[g.getOptind()+1];

        // Create statement mapper
        StatementMapper mapper=new StatementMapper(leftFileStr, version, 
                rightFileStr, version);
       
        // configure the statement mapper
        mapper.setUseMinTokenOrTextEditDistance(useMinOfTokenOrTextEditDistance);
        mapper.setCanfora(canforaThreshold);
        
        mapper.setClassMappingThreshold(classMappingThreshold);
        mapper.setFieldMappingThreshold(fieldMappingThreshold);
        mapper.setMethodMappingThreshold(methodMappingThreshold);
        mapper.setRunTokenEditDistance(useTokenEditDistance);
        
        // Run the mapper
        StatementMappingResultSet rs=mapper.runStatementMapper();
        
        // find the valid matches
        mapper.setValidMappings(rs);
        // find near-miss matches if we're looking for them
        mapper.setProbablePossibleMappings(rs);

        for (StatementMappingEntry e : rs) {
            if (e.toString().length()>0) {
                System.out.println(e);
            }
        }
    }
}
